#define BOOST_TEST_MODULE testAddElement

#include <memory>
#include <thread>

#include <boost/test/unit_test.hpp>

#include <crow.h>

#include "common/api/client.h"
#include "common/api/result.hpp"
#include "common/api/server.h"
#include "common/api/server_helper.hpp"

#include "common/elements/element_type.hpp"
#include "common/elements/item.h"
#include "common/elements/user.h"

#include "common/more/uuid.h"

class Server final
{
public:
    Server()
        : m_crowApplication(new crow::SimpleApp)
    {
        ADD_CROW_ROUTE_ADD_ELEMENT(
            (*m_crowApplication),
            [this](
                const Uuids::Uuid& sessionUuid,
                std::shared_ptr<Elements::Element> element
            ) -> unsigned
            {
                if (sessionUuid.is_nil())
                    return 0;

                if (Elements::ElementType::User == element->elementType())
                    return 9;

                return 0;
            }
        );
        m_runThread.reset(new std::thread(
            [this]()
            { m_crowApplication->port(8080).multithreaded().run(); }
        ));
        m_stopThread.reset(new std::thread(
            [this]()
            { stop(); }
        ));
    }

    ~Server()
    {
        m_stopThread->join();
        m_runThread->join();
    }

private:
    std::unique_ptr<crow::SimpleApp> m_crowApplication;
    std::unique_ptr<std::thread> m_runThread;
    std::unique_ptr<std::thread> m_stopThread;

    void stop()
    {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        m_crowApplication->stop();
    }
};

Server server;
Api::Client client("http://127.0.0.1:8080");

BOOST_AUTO_TEST_CASE(testCorrectAddElement)
{
    const auto uuid = Uuids::newUuid();
    const auto element = std::make_shared<Elements::User>();
    const auto result = client.addElement(uuid, element);
    BOOST_CHECK(result.m_isSuccess);
    BOOST_CHECK(result.m_id == 9);
}

BOOST_AUTO_TEST_CASE(testNonCorrectAddElement)
{
    const auto uuid = Uuids::newUuid();
    const auto element = std::make_shared<Elements::Item>();
    const auto result = client.addElement(uuid, element);
    BOOST_CHECK(!result.m_isSuccess);
    BOOST_CHECK(result.m_id == 0);
}
